//
//  JQFYMusicPlayer.m
//  JQFY
//
//  Created by 代辉 on 2017/8/18.
//  Copyright © 2017年 yannis. All rights reserved.
//

#import "JQFYMusicPlayer.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import "CALayer+Animation.h"

@interface JQFYMusicPlayer () <NSURLSessionDownloadDelegate,AVAudioPlayerDelegate>

@property (nonatomic,assign) NSInteger currentSelectIndex;

@property (nonatomic, strong) NSURLSession *downloadSession;

@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@end

@implementation JQFYMusicPlayer {
    AVPlayer *_player;
    NSTimer *_timer;
    NSInteger _currentIndex;
    AVPlayerItem *_playItem;
    NSString *_cachePath;
    NSString *_currentPath;
    AVAudioPlayer *_localPlayer;
}

IMPLEMENTATION_SINGLETON(JQFYMusicPlayer)

- (instancetype)init
{
    self = [super init];
    if (self) {
        
        self.currentSelectIndex = -1;
        _timer = nil;
        _player = nil;
        self.currentEffView = nil;
        self.status = JQFYMusicPlayerStatusPaused;
        // 监视播放状态发生变化
        [self addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
        
        // 监视播放歌曲的索引发生变化
        [self addObserver:self forKeyPath:@"currentSelectIndex" options:NSKeyValueObservingOptionNew context:nil];
        
        // 自我实现歌曲状态发生改变的时候回调
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(musicPlayerStatusDidChangedNotification:) name:JQFYMusicPlayerStatusDidChangedNotification object:self];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(recommendMusicPlay:)
                                                     name:@"recommendMusicPlay"
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(playerItemDidReachEnd)
                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:_player];
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
        
        self.numIndex = [[NSUserDefaults standardUserDefaults] integerForKey:NUMBERINDEX];
    }
    return self;
}
#pragma mark - 监听歌曲播放完成后回调 -
- (void)playerItemDidReachEnd
{
    if (self.playingSong == nil) {
        return; 
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionCategoryPlayback object:_player];
    
    [self playingFinish];
    
}

// 当前播放歌曲对象
- (JQFYSong *)playingSong {
    if(self.songs == nil || self.currentSelectIndex >= self.songs.count || self.currentSelectIndex == -1) {
        return nil;
    }
    if (_playIndexPath.section == 0) {
        return [self.recommendMusics objectAtIndex:self.currentSelectIndex];
    }
    return [self.songs objectAtIndex:self.currentSelectIndex];
}

// 歌曲总时长
- (float)totalTime {
    if(_player) {
        return CMTimeGetSeconds([_player.currentItem duration]);
    }
    if (_localPlayer) {
        return _localPlayer.duration;
    }
    return 0.0;
}
#pragma mark - 控制 -
// 设置当前播放时间
- (void)setCurrentTime:(float)currentTime {
    if(_player) {
        [_player seekToTime:CMTimeMake((int64_t)currentTime, 1.0)];
    }
    if (_localPlayer) {
        [_localPlayer setCurrentTime:currentTime];
    }
}
/// 获取当前时间
- (float)currentTime {
    if(_player) {
        return CMTimeGetSeconds([_player.currentItem currentTime]);
    }
    if (_localPlayer) {
        return _localPlayer.currentTime;
    }
    return 0.0;
}

// 开始监视当前时间发生改变回调
- (void)startObserveCurrentTime {
    [self stopObserveCurrentTime];
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 60.0 target:self selector:@selector(doObserveCurrentTime) userInfo:nil repeats:YES];
}

// 结束监视当前时间发生改变回调
- (void)stopObserveCurrentTime {
    if(_timer != nil) {
        if([_timer isValid]) [_timer invalidate];
        _timer = nil;
    }
}

// 歌曲状态发生改变回调
- (void)musicPlayerStatusDidChangedNotification:(NSNotification *)notification {
    
    JQFYMusicPlayerStatus status = [notification.userInfo[kMusicPlayerStatus] integerValue];
    
    
    if(status == JQFYMusicPlayerStatusPlaying) {
        // 当歌曲开始播放的时候开始监听当前时间发生变化
        [self startObserveCurrentTime];
        
    } else {
        // 如果歌曲结束播放停止监听
        [self stopObserveCurrentTime];
    }
}
- (void)doObserveCurrentTime {
    
    NSDictionary *songInfo;
    if (_player) {
        
        songInfo = @{
                     kCurrentTime:@(CMTimeGetSeconds([_player.currentItem currentTime])),
                     kTotalTime:@(CMTimeGetSeconds([_player.currentItem duration]))
                     };
    } else {
        songInfo = @{
                     kCurrentTime:@(_localPlayer.currentTime),
                     kTotalTime:@(_localPlayer.duration)
                     };
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:JQFYMusicPlayerCurrentTimeDidChangedNotification
                                                        object:self
                                                      userInfo:songInfo];
    
    [self updateLockedScreenInfo];
    
}

// 更新锁屏界面信息
- (void)updateLockedScreenInfo
{
    UIImageView *artWorkImage = [UIImageView  new];
    [artWorkImage sd_setImageWithURL:[NSURL URLWithString:self.playingSong.music_cover_path] placeholderImage:[UIImage imageNamed:@"Electronicmusiclabel（合并）（合并）"]];
    MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
    center.nowPlayingInfo = @{
                              MPNowPlayingInfoPropertyElapsedPlaybackTime:@(self.currentTime),
                              MPMediaItemPropertyTitle:self.playingSong.music_name,
                              MPMediaItemPropertyArtist:self.playingSong.music_auth,
                              MPMediaItemPropertyPlaybackDuration:@(self.totalTime),
                              MPMediaItemPropertyArtwork:[[MPMediaItemArtwork alloc] initWithImage:artWorkImage.image]
                              };
}

#pragma mark - 播放推荐位音乐 -
- (void)recommendMusicPlay:(NSNotification *)noti
{
    NSIndexPath *indexPath = noti.object;
    _playIndexPath = indexPath;
   
    [self playAtIndex:indexPath.row];
}

- (void)isNetWorkPlaying
{
    if (_player) {
        if (self.isPlaying) {
            return;
        }
        [_player play];
    }
}
- (void)playAtIndex:(NSInteger)index
{
    
    if (_playIndexPath.section == 0) {
        if(self.recommendMusics == nil || self.recommendMusics.count == 0) {
            return;
        }
        // 判断所选的歌曲是否是正在播放歌曲,同时播放器对象是真的存在的
        if(index == self.currentSelectIndex && _player != nil) {
            [_player play];
            // 注意:播放状态发生变化
            self.status = JQFYMusicPlayerStatusPlaying;
            return;
        }
        if(index == self.currentSelectIndex && _localPlayer != nil) {
            [_localPlayer play];
            // 注意:播放状态发生变化
            self.status = JQFYMusicPlayerStatusPlaying;
            return;
        }
        
        
        // 处理如果是点击上一曲的情况,如果上一曲已经到达第一首,就让他回到最后一首歌曲
        if(index < 0) {
            index = self.recommendMusics.count - 1;
        }
        
        // 处理如果是点击最后一曲的情况,如果最后一曲已经是最后一曲,就让它回到第一首歌曲
        if(index >= self.recommendMusics.count) {
            index = 0;
        }
        self.playIndexPath = [NSIndexPath indexPathForRow:index inSection:self.playIndexPath.section];
        JQFYSong *song = self.recommendMusics[index];
        [self playWithSongPath:song];
        self.currentSelectIndex = index;
    } else {
        
        if(self.songs == nil || self.songs.count == 0) {
            return;
        }
        
        // 判断所选的歌曲是否是正在播放歌曲,同时播放器对象是真的存在的
        if(index == self.currentSelectIndex && _player != nil) {
            [_player play];
            // 注意:播放状态发生变化
            self.status = JQFYMusicPlayerStatusPlaying;
            return;
        }
        if(index == self.currentSelectIndex && _localPlayer != nil) {
            [_localPlayer play];
            // 注意:播放状态发生变化
            self.status = JQFYMusicPlayerStatusPlaying;
            return;
        }
        
        // 处理如果是点击上一曲的情况,如果上一曲已经到达第一首,就让他回到最后一首歌曲
        if(index < 0) {
            index = self.songs.count - 1;
        }
        
        // 处理如果是点击最后一曲的情况,如果最后一曲已经是最后一曲,就让它回到第一首歌曲
        if(index >= self.songs.count) {
            index = 0;
        }
        self.playIndexPath = [NSIndexPath indexPathForRow:index inSection:self.playIndexPath.section];
        JQFYSong *song = self.songs[index];
        [self playWithSongPath:song];
        self.currentSelectIndex = index;
    }
}

- (void)playWithSongPath:(JQFYSong *)song
{
    NSString *songPath = [song.music_path lastPathComponent];
    _cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:songPath];
    // 判断是否有缓存
    if (![[NSFileManager defaultManager] fileExistsAtPath:_cachePath]) {
        // 缓存歌曲
        _currentPath = _cachePath;
        [self cacheMusicWithMusicPath:song.music_path];
        NSURL *audioURL = [NSURL URLWithString:song.music_path];
        // 判断是否有本地歌曲播放并处理
        if (_localPlayer.isPlaying) {
            [_localPlayer stop];
            _localPlayer = nil;
        }
        // 播放网络歌曲
        if (_player == nil) {
            _player = [AVPlayer playerWithURL:audioURL];
        } else {
            [_player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:[NSURL URLWithString:song.music_path]]];
        }
        _playItem = _player.currentItem;
        [_player play];
    } else {
        // 判断是否有网络歌曲播放 并处理
        if (self.isPlaying) {
            [_player pause];
            _player = nil;
        }
        // 播放本地歌曲
        _localPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:_cachePath] error:nil];
        _localPlayer.delegate = self;
        [_localPlayer prepareToPlay];
        [_localPlayer play];
    }
    
    self.status = JQFYMusicPlayerStatusPlaying;
}
#pragma mark - 本地歌曲结束时调用 -
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    [self playingFinish];
}

- (void)playingFinish
{
    if (_numIndex == -888) {
        NSInteger index ;
        if (self.playIndexPath.section == 1) {
            index = arc4random_uniform((uint32_t)self.songs.count - 1);
        } else {
            index = arc4random_uniform((uint32_t)self.recommendMusics.count - 1);
        }
        
        if (index == _currentIndex) {
            if (self.playIndexPath.section == 1) {
                index = arc4random_uniform((uint32_t)self.songs.count - 1);
            } else {
                index = arc4random_uniform((uint32_t)self.recommendMusics.count - 1);
            }
        }
        [self playAtIndex:index];
        _currentIndex = index;
        return;
    }
    if (self.numIndex == NSIntegerMax) {
        [_player seekToTime:CMTimeMake(0, 1)];
        [_player play];
        return;
    }
    [self next];
}
- (BOOL)isPlaying
{
    if (_player) {
        
        return _player.rate == 1;
    }
    return _localPlayer.isPlaying;
}

- (void)play
{
    [self playAtIndex:self.currentSelectIndex];
}

- (void)prev
{
    [self playAtIndex:self.currentSelectIndex - 1];
}

- (void)pause
{
    if (_player != nil) {
        
        [_player pause];
    } else if (_localPlayer != nil) {
        [_localPlayer pause];
    }
    self.status = JQFYMusicPlayerStatusPaused;
}

- (void)next
{
    [self playAtIndex:self.currentSelectIndex + 1];
}
#pragma mark - 设置音量 -
- (void)setVolume:(CGFloat)volume
{
    if (_localPlayer != nil) {
        
        _localPlayer.volume = volume;
    }
    if (_player != nil) {
        
        _player.volume = volume;
    }
}
#pragma mark - KVO 通知 -
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context {
    if([keyPath isEqualToString:@"status"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:JQFYMusicPlayerStatusDidChangedNotification object:self userInfo:@{kMusicPlayerStatus:@(self.status)}];
    } else if([keyPath isEqualToString:@"currentSelectIndex"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:JQFYMusicPlayerPlayingSongDidChangedNotification object:self userInfo:@{kMusicPlayerPlayingSong:self.playingSong}];
    }
}

#pragma mark - 缓存歌曲 -
- (void)cacheMusicWithMusicPath:(NSString *)path
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        // 实例化下载session,同时设置代理
        self.downloadSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue new]];
        NSURL *url = [NSURL URLWithString:path];
        
        if (self.downloadTask) {
            [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
                [[NSFileManager defaultManager] removeItemAtPath:_currentPath error:nil];
                self.downloadTask = nil;
            }];
        }
        // 2.使用自定义下载sessioin,发起和启动下载任务
        self.downloadTask = [self.downloadSession downloadTaskWithURL:url];
        [self.downloadTask resume];
    });
}

/// 监听下载结束的代理方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    // location : 文件临时缓存路径.拷贝文件到另外一个不会被删除的路径
    [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:_cachePath error:NULL];
    self.downloadTask = nil;

}
// 下载出错也要销毁session
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
{
    [[NSFileManager defaultManager] removeItemAtPath:_currentPath error:nil];
    [session invalidateAndCancel];
}
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [_timer invalidate];
}
@end
